package com.bicon.botu.mall.goods.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.bicon.botu.core.base.common.BusinessException;
import com.bicon.botu.core.base.common.Constants;
import com.bicon.botu.core.base.common.utils.BeanMapper;
import com.bicon.botu.core.base.repository.redis.RedisHandler;
import com.bicon.botu.core.dto.GlobalSearchDTO;
import com.bicon.botu.mall.goods.commons.GoodsConstants;
import com.bicon.botu.mall.goods.dto.OrderVerifyDto;
import com.bicon.botu.mall.goods.dto.ProductRepertoryIdListDto;
import com.bicon.botu.mall.goods.entity.Product;
import com.bicon.botu.mall.goods.entity.ProductComment;
import com.bicon.botu.mall.goods.entity.ProductRepertory;
import com.bicon.botu.mall.goods.entity.TraceElement;
import com.bicon.botu.mall.goods.mapper.ProductMapper;
import com.bicon.botu.mall.goods.service.*;
import com.bicon.botu.mall.goods.vo.*;
import com.fasterxml.jackson.databind.type.ReferenceType;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.util.*;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author 孙永刚
 * @since 2017-07-19
 */
@Service
@Transactional
public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> implements IProductService {

    @Autowired
    private ProductMapper productMapper;

    @Autowired
    private ITraceElementService elementService;

    @Autowired
    private IProductRepertoryService repertoryService;

    @Autowired

    private IProductPictureService pictureService;

    @Autowired
    private RedisHandler redisHandler;

    @Autowired
    private NoticeOfReductionService noticeOfReductionService;

    @Autowired
    IProductCommentService iProductCommentService;

    /**
     * 添加商品基本信息
     *
     * @param classfily
     * @param description
     * @param isFreeFreight
     * @param isProduct
     * @param lable
     * @param logisticsType
     * @param noticeNum
     * @param productName
     * @param productType
     * @param upShelves
     * @param supplier
     * @param weight
     * @param details
     * @param brandId
     * @param productRegion
     * @param isOnBefore
     * @param isOnAfter
     * @param beforeText
     * @param afterText
     * @param traceElement
     * @param saveOrUpdate
     * @param productId
     * @return
     */
    public Product addProduct(String classfily, String description, String isFreeFreight, String isProduct, String lable, String logisticsType, Integer noticeNum, String productName, String productType, String upShelves, String supplier, double weight, String details, String brandId, String productRegion,
                              String isOnBefore, String isOnAfter, Integer beforeText, Integer afterText, String traceElement, String saveOrUpdate, String productId, String productCode, BigDecimal buyingPrice) {
        Product product = new Product();
        if (saveOrUpdate.equals(GoodsConstants.SAVE)) {
            product.preInsert();
        } else if (saveOrUpdate.equals(GoodsConstants.UPDATE)) {
            product.preUpdate();
            product.setId(productId);
        }
        product.setCategoryId(classfily);
        product.setDescription(description);
        product.setIsFreeFreight(isFreeFreight);
        product.setIsProduct(isProduct);
        product.setLable(lable);
        product.setLogisticsType(logisticsType);
        product.setNoticeNum(noticeNum);
        product.setProductName(productName);
        product.setProductType(productType);
        product.setUpShelves(upShelves);
        product.setServer(supplier);
        product.setWeight(weight);
        product.setServer(supplier);
        product.setDetails(details);
        product.setBrandId(brandId);
        product.setProductRegion(productRegion);
        product.setIsOnBefore(isOnBefore);
        product.setIsOnAfter(isOnAfter);
        product.setBeforeText(beforeText);
        product.setAfterText(afterText);
        product.setTraceElement(traceElement);
        product.setProductCode(productCode);
        product.setShowState("0");
        product.setBuyingPrice(buyingPrice == null ? new BigDecimal("0") : buyingPrice);
        product.insertOrUpdate();
        return product;
    }


    /**
     * 添加商品sku信息
     *
     * @param productAttr
     * @param saveOrUpdate
     * @param productId
     * @return
     */
    @Override
    // @Async("priceDownNoticeAsync")
    public Boolean addRepertoryInfo(String productAttr, String saveOrUpdate, String productId, String productName) {
        boolean result = false;
        if (!StringUtils.isEmpty(productAttr)) {
            List<ProductRepertory> list = JSONObject.parseArray(productAttr, ProductRepertory.class);
            List<ProductRepertory> newList = new ArrayList<>(list.size());
            BigDecimal bigDecimal = getProductMinPrice(list);
            Product product = new Product();
            product.setId(productId);
            product.setProductPrice(bigDecimal);
            product.updateById();
            for (ProductRepertory productRepertory : list) {
                if (productRepertory.getId() == null) {
                    productRepertory.preInsert();
                    productRepertory.setProductId(productId);
                } else {
                    productRepertory.preUpdate();
                }
                newList.add(productRepertory);
            }
            //如果是修改
            if (saveOrUpdate.equals(GoodsConstants.UPDATE)) {
                //查询修改后商品sku集合
                List<PriceDownNoticeVo> listVo = getProductSkuPrice(productId, list, productName);
                if (listVo.size() > 0) {
                    //调用刘齐方法
                    noticeOfReductionService.systemInfo(listVo);
                }
            }
            result = repertoryService.insertOrUpdateBatch(newList);
        }
        return result;
    }

    /**
     * 添加微量元素
     *
     * @param element
     * @param operation
     * @param productId
     * @return
     */
    public Boolean addTraceElement(String element, String operation, String productId) {
        if (!StringUtils.isEmpty(element)) {
            List<TraceElement> list = JSONObject.parseArray(element, TraceElement.class);
            List<TraceElement> newList = new ArrayList<>(list.size());
            for (int i = 0; i < list.size(); i++) {
                TraceElement element1 = list.get(i);
                if (StringUtils.isEmpty(element1.getId())) {
                    element1.setSort(i + 1);
                    element1.setProductId(productId);
                    element1.preInsert();
                } else {
                    element1.setSort(i + 1);
                    element1.preUpdate();
                }
                newList.add(element1);
            }
            return elementService.insertOrUpdateBatch(newList);

        }

        return false;
    }

    /**
     * 添加商品
     *
     * @param productType   商品类型 非定制  定制
     * @param classfily     分类Id
     * @param brandId       品牌Id
     * @param supplier      供货商
     * @param buyingPrice   进货价
     * @param productName   商品名
     * @param description   描述
     * @param lable         标签
     * @param details       详细描述
     * @param weight        重量
     * @param noticeNum     警告数量
     * @param upShelves     是否上架
     * @param isProduct     是否作为商品
     * @param isFreeFreight 是否免运费
     * @param logisticsType 物流商
     * @param productAttr   产品skujson
     * @param productRegion 产品销售区域
     * @param isOnBefore    是否启用前身文字
     * @param isOnAfter     是否启用后身文字定义
     * @param beforeText    前身文字
     * @param afterText     后身文字
     * @param traceElement  是否启用微量元素自定义
     * @param element       微量元素json
     * @param saveOrUpdate  操作类型
     * @param productId     商品Id
     * @param productCode   商品编号
     * @return
     */
    @Override

    public Boolean addProductInfo(String classfily, String description, String isFreeFreight, String isProduct, String lable, String logisticsType, Integer noticeNum, String productName, String productType, String upShelves, String supplier, double weight, String details, String brandId, String productRegion, String isOnBefore, String isOnAfter, Integer beforeText, Integer afterText, String traceElement, String saveOrUpdate, String productId, String productAttr, String element,
                                  String productCode, BigDecimal buyingPrice, String pictureStr) {
        boolean result = false;
        Product product = addProduct(classfily, description, isFreeFreight, isProduct, lable, logisticsType, noticeNum, productName, productType, upShelves, supplier, weight, details, brandId, productRegion, isOnBefore, isOnAfter, beforeText, afterText, traceElement, saveOrUpdate, productId, productCode, buyingPrice);
        pictureService.addPicture(pictureStr, product.getId(), saveOrUpdate);
        result = addRepertoryInfo(productAttr, saveOrUpdate, product.getId(), product.getProductName());
        //如果是定制商品
        if (product.getProductType().equals(GoodsConstants.CUSTOM_STATE1)) {
            if (traceElement.equals(GoodsConstants.CUSTOM_STATE1)) {
                result = addTraceElement(element, saveOrUpdate, product.getId());
            }
        }
        //查找商品最低价格
        List<ProductRepertory> list = JSONObject.parseArray(productAttr, ProductRepertory.class);
        BigDecimal bigDecimal = getProductMinPrice(list);
        product.setProductPrice(bigDecimal);

        cacheProductInfo(product, pictureStr);
        return result;
    }

    @Override
    public Page getProductList(Page<ProductListVo> page, Map<String, Object> map) {

        List<ProductListVo> listVos = productMapper.getProductList(page, map);
        page.setRecords(listVos);
        return page;
    }

    /**
     * 获取最低的商品价格
     *
     * @param list
     * @return
     */
    @Override
    public BigDecimal getProductMinPrice(List<ProductRepertory> list) {
        BigDecimal[] bigDecimals = new BigDecimal[list.size()];
        int i = 0;
        for (ProductRepertory repertory : list) {
            bigDecimals[i] = repertory.getPrice();
            i++;
        }
        BigDecimal min = bigDecimals[0];
        for (int j = 0; j < bigDecimals.length; j++) {
            if (bigDecimals[j].doubleValue() < bigDecimals[0].doubleValue()) {
                min = bigDecimals[j];
            }
        }
        return min;
    }


    /**
     * 获取有改动商品价格的库存
     *
     * @param productId
     * @param list
     * @return
     */
    public List<PriceDownNoticeVo> getProductSkuPrice(String productId, List<ProductRepertory> list, String productName) {

        List<ProductRepertory> repertoryList = repertoryService.selectList(new EntityWrapper<ProductRepertory>().eq("product_id", productId));
        List<PriceDownNoticeVo> newList = new ArrayList<>();
        for (ProductRepertory repertory : repertoryList) {
            PriceDownNoticeVo vo = new PriceDownNoticeVo();
            for (ProductRepertory repertoryOld : list) {
                if (repertory.getId().equals(repertoryOld.getId())) {
                    if (repertory.getPrice().doubleValue() != repertoryOld.getPrice().doubleValue()) {
                        vo.setProductPrice(repertoryOld.getPrice());
                        vo.setProductName(productName);
                        vo.setProductSku(repertoryOld.getSkuName());
                        vo.setRepertoryId(repertoryOld.getId());
                        newList.add(vo);
                    }
                }

            }
        }
        return newList;

    }


    /**
     * 添加或修改商品时将信息缓存到redis
     *
     * @param product
     * @param picture
     */
    @Override
    public void cacheProductInfo(Product product, String picture) {
        ProductVo vo = BeanMapper.map(product, ProductVo.class);
        String p = "";
        if (!StringUtils.isEmpty(picture)) {
            p = picture.split(",")[0];
        }
        vo.setPicture(p);
        redisHandler.getLocalRedisTemplate().cacheStringValue(GoodsConstants.PRODUCT_INFO, product.getId(), JSONObject.toJSONString(vo));
    }


    @Override
    public void batchOpertion(String ids, String opertion) {
        //0 批量上架 1.批量下架  2.批量删除逻辑 3.批量商品状态还原 4.商品批量删除物理
        String[] id = ids.split(",");
        for (int i = 0; i < id.length; i++) {

            ProductVo vo = JSONObject.parseObject(redisHandler.getLocalRedisTemplate().getStringValue(GoodsConstants.PRODUCT_INFO, id[i]), ProductVo.class);
            switch (opertion) {
                //批量上架
                case GoodsConstants.PRODUCT_UP_SHELVES:
                    vo.setUpShelves(GoodsConstants.PRODUCT_UP_SHELVES);
                    redisHandler.getLocalRedisTemplate().cacheStringValue(GoodsConstants.PRODUCT_INFO, vo.getId(), JSONObject.toJSONString(vo));
                    break;
                //批量下架
                case GoodsConstants.PRODUCT_DOWN_SHELVES:
                    vo.setUpShelves(GoodsConstants.PRODUCT_DOWN_SHELVES);
                    redisHandler.getLocalRedisTemplate().cacheStringValue(GoodsConstants.PRODUCT_INFO, vo.getId(), JSONObject.toJSONString(vo));
                    break;
                //批量逻辑删除
                case GoodsConstants.PRODUCT_BATCH_DELETE:
                    vo.setLogicDelete(GoodsConstants.DEL_LOGIC_DELETE);
                    redisHandler.getLocalRedisTemplate().cacheStringValue(GoodsConstants.PRODUCT_INFO, vo.getId(), JSONObject.toJSONString(vo));
                    break;

                //批量还原
                case GoodsConstants.PRODUCT_BATCH_UPDATE:
                    vo.setLogicDelete(GoodsConstants.DEL_LOGIC_NORMAL);
                    redisHandler.getLocalRedisTemplate().cacheStringValue(GoodsConstants.PRODUCT_INFO, vo.getId(), JSONObject.toJSONString(vo));
                    break;

                case GoodsConstants.PRODUCT_BATCH_REALLY_DELETE:
                default:
                    redisHandler.getLocalRedisTemplate().remove(GoodsConstants.PRODUCT_INFO, vo.getId());

            }


        }

    }

    /**
     * 查询最大和最小金额
     *
     * @param map
     * @return
     */
    @Override
    public ProductPriceVo getMaxPriceAndMinPrice(Map<String, Object> map) {
        return productMapper.getMaxPriceAndMinPrice(map);
    }

    /**
     * 查询删除或下架的商品中是否包含展示商品
     *
     * @param list
     * @return
     */
    @Override
    public Integer searchChannelGoods(List<String> list) {
        return productMapper.searchChannelGoods(list);
    }

    /**
     * 查询删除或下架的商品中是否包含展示商品
     *
     * @param goodId
     * @return
     */
    @Override
    public Integer searCarefullyGoods(String goodId) {
        return productMapper.searCarefullyGoods(goodId);
    }

    /**
     * 为全局搜索提供商品列表表数据
     *
     * @param page
     * @param map
     * @return
     */
    @Override
    public Page<GlobalSearchDTO> getProductListForRpc(Page<GlobalSearchDTO> page, Map<String, Object> map) {
        List<GlobalSearchDTO> list = productMapper.getProductListForRpc(page, map);
        page.setRecords(list);
        return page;
    }

    /**
     * 根据商品名称搜索商品
     *
     * @param page
     * @param map
     * @return
     */
    @Override
    public List<ProductDrugVo> selectProductList(Page<ProductDrugVo> page, Map<String, Object> map) {
        List<ProductDrugVo> list = productMapper.selectProductList(page, map);
        return list;
    }

    @Override
    public LogisticsCenterDto selectLogisticsCenter(String productId) {
        return null;
    }


    /**
     * 根据商品名称查询列表(医疗)
     *
     * @param productName
     * @return
     */
    @Override
    public List<DrugPriceVo> findByProductName(String productName) {
        Map<String, String> map = new HashMap<String, String>();
        map.put("productName", productName);
        List<DrugPriceVo> drugPriceVoList = productMapper.findByProductName(map);
        return drugPriceVoList;
    }

    /**
     * 多个商品库存id 查询是否商品为可用状态
     *
     * @param productRepertoryIdList 多个商品库存id
     * @return
     */

    @Override
    public List<ProductRepertoryIdListDto> selectProductRepertory(List<String> productRepertoryIdList) {
        List<ProductRepertoryIdListDto> listDto = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(productRepertoryIdList)) {
            listDto = productMapper.selectProductRepertory(productRepertoryIdList);

        }
        return listDto;
    }

    /**
     * 根据商品信息验证商品
     *
     * @param verifyDtoListJson 多个商品库存
     * @return
     */

    @Override
    public Boolean verifyProduct(String verifyDtoListJson) {
        if (StringUtils.isEmpty(verifyDtoListJson)) {
            throw new BusinessException("商品信息不能为空");
        }
        Type type = new TypeReference<List<OrderVerifyDto>>(){}.getType();
        List<OrderVerifyDto> orderVerifyDtoList = JSONObject.parseObject(verifyDtoListJson,type);

        Set<OrderVerifyDto> dtoList = new HashSet<>();


        //获取多个库存id
        String[] skuIds = orderVerifyDtoList.stream().map(OrderVerifyDto::getGoodsId).toArray(String[]::new);
        List<String> a = Arrays.asList(skuIds);
        //去重复
        List<String> listWithoutDup = new ArrayList<String>(new HashSet<String>(a));

        //针对于定制商品
        for (String id : listWithoutDup) {
            int i = 0;
            for (OrderVerifyDto orderVerifyDto : orderVerifyDtoList) {
                if (id.equals(orderVerifyDto.getGoodsId())) {
                    OrderVerifyDto orderVerifyDto1 = new OrderVerifyDto();
                    orderVerifyDto1.setGoodsId(orderVerifyDto.getGoodsId());
                    orderVerifyDto1.setGoodsNumber(i += orderVerifyDto.getGoodsNumber());
                    dtoList.add(orderVerifyDto1);
                }
            }
        }
        List<ProductRepertory> repertoryList = repertoryService.selectList(new EntityWrapper<ProductRepertory>()
                .eq("logic_delete", Constants.DEL_LOGIC_NORMAL).in("id", listWithoutDup));
        Map<String,OrderVerifyDto> map = new HashMap<>(16);
        for (OrderVerifyDto orderVerifyDto : dtoList) {
            map.put(orderVerifyDto.getGoodsId(),orderVerifyDto);
        }
        for (ProductRepertory productRepertory : repertoryList) {
            OrderVerifyDto orderVerifyDto = map.get(productRepertory.getId());
            if (productRepertory.getId().equals(orderVerifyDto.getGoodsId())) {
                if (orderVerifyDto.getGoodsNumber() <= productRepertory.getProductNum()) {
                    productRepertory.setProductNum(productRepertory.getProductNum()-orderVerifyDto.getGoodsNumber()>=0? productRepertory.getProductNum()-orderVerifyDto.getGoodsNumber(): 0);
                    productRepertory.preUpdate();
                } else {
                    return false;
                }

            }
        }
        return repertoryService.updateBatchById(repertoryList);
    }

    /**
     * 商品上下架数量统计
     * @return
     */
    @Override
    public List<Map<Integer, Object>> shelvesTotal() {
        List<Map<Integer,Object>> mapList= productMapper.shelvesTotal();
        return mapList;
    }
//    /**
//     * 减少商品库存
//     *
//     * @param verifyDtoList 多个商品库存
//     * @return
//     */
//
//    @Override
//    public Boolean reduceProduct(List<OrderVerifyDto> verifyDtoList) {
//        if (CollectionUtils.isEmpty(verifyDtoList)){
//            throw new BusinessException("参数错误");
//        }
//
//
//
//
//        return null;
//    }

    @Override
    public Map<String, Object> goodsStatistic() {
        //商品上下架
        List<Map<Integer,Object>> objectList = this.shelvesTotal();
        //库存警告统计
        Map<String,Object> repertoryMap = repertoryService.repertoryTotal();
        //评论未处理
        int level1 = iProductCommentService.selectCount(new EntityWrapper<ProductComment>().eq("reply_status", 1).eq("logic_delete", Constants.DEL_LOGIC_NORMAL));
        Map<String, Object> map = new HashMap<>();
        //上架
        map.put("putaway",objectList.get(0).get("COUNT(*)"));
        //下架
        map.put("unshelve",objectList.get(1).get("COUNT(*)"));
        //商品缺货
        map.put("stockout",repertoryMap.get("stockout"));
        //库存警告
        map.put("repertoryWarmTotal",repertoryMap.get("repertoryWarmTotal"));
        //评论未处理
        map.put("unReply",level1);
        return map;
    }
}
